package aeemqx

import (
	"context"
	"devops-super/internal/consts"
	"devops-super/internal/dao"
	"devops-super/internal/model/do"
	"devops-super/internal/model/mymodel"
	"devops-super/internal/service"
	"devops-super/pb"
	"devops-super/utility/util/timeUtil"
	"encoding/json"
	"errors"
	"github.com/gogf/gf/v2/util/gconv"
	"strings"
	"time"

	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/golang/protobuf/proto"
)

// 在handleAeIotDeviceOpResponse函数中添加日志清理逻辑
var lastCleanDeviceStateLogTime *gtime.Time

// ConsumeDevicePub 接收设备上报
func (s *sAeemqx) ConsumeDevicePub(ctx context.Context, payload []byte) (err error) {
	message := pb.SensorMessage{}
	err = proto.Unmarshal(payload, &message)
	if err != nil {
		glog.Error(ctx, err)
		return err
	}
	glog.Line().Info(ctx, message.NodeId)
	glog.Line().Info(ctx, message.GetIotDeviceStateResponse())
	oneofDebug := true
	oneof := ""
	switch message.Msg.(type) {
	case *pb.SensorMessage_AeSensorData: //旧版的参数波形 这里只支持收参数了
		oneof = "SensorMessage_AeSensorData"
		err = s.handleAeSensorDataV1(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_SensorData: //统一的参数数据
		oneof = "SensorMessage_SensorData"
		err = s.handleCommonSensorData(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_AeWave: // ae波形数据
		oneof = "SensorMessage_AeWave"
		err := s.implementReceiveWaveDataAE(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_ViSensorWaveData: //vi波形数据
		oneof = "SensorMessage_ViSensorWaveData"
		err := s.implementReceiveWaveDataVI(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_AeMeasureConfig:
		oneof = "SensorMessage_AeMeasureConfig"
		err = s.implementHandleAeMeasureConfig(ctx, message.NodeId, message.GetAeMeasureConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_FirConfig:
		oneof = "SensorMessage_FirConfig"
		err = s.implementHandleAeFirConfig(ctx, message.NodeId, message.GetFirConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_AeFFTConfig:
		oneof = "SensorMessage_AeFFTConfig"
		err = s.implementHandleAeFFTConfig(ctx, message.NodeId, message.GetAeFFTConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_AeTimingConfig:
		oneof = "SensorMessage_AeTimingConfig"
		err = s.implementHandleAeTimingConfig(ctx, message.NodeId, message.GetAeTimingConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_LevelConfig: //评级配置 v2版本
		oneof = "SensorMessage_LevelConfig"
		err = s.implementHandleLevelConfig(ctx, message.NodeId, message.GetLevelConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_FrpConfig:
		oneof = "SensorMessage_FrpConfig"
		err = s.implementHandleFrpConfig(ctx, message.NodeId, message.GetFrpConfig())
		if err != nil {
			return err
		}
	case *pb.SensorMessage_ViMeasureConfig:
		oneof = "SensorMessage_ViMeasureConfig"
		err = s.implementHandleViMeasureConfig(ctx, message.NodeId, message.GetViMeasureConfig())
		if err != nil {
			return err
		}
		_ = service.Device().ChangeVersion(ctx, message.NodeId, message.Ver)
	case *pb.SensorMessage_IotDeviceOpResponse: // 设备配置操作后的反馈
		oneof = "SensorMessage_IotDeviceOpResponse"
		err = s.handleAeIotDeviceOpResponse(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_AeAstResult: // ast结果
		oneof = "SensorMessage_AeAstResult"
		err = s.handleAeAstResult(ctx, &message)
		if err != nil {
			return err
		}
	case *pb.SensorMessage_LevelResult: //评级数据 v2版本
		oneof = "SensorMessage_AeAstResult"
		// TODO
		err = s.handleLevelData(ctx, &message)
		if err != nil {
			return err
		}
	default:
		oneof = "default"
	}
	if oneofDebug {
		glog.Line().Info(ctx, oneof)
	}
	return
}

// handleCommonSensorData 通用的物联网数据接收
func (s *sAeemqx) handleCommonSensorData(ctx context.Context, message *pb.SensorMessage) (err error) {
	deviceNo := message.GetNodeId()
	paramData := message.GetSensorData()
	if paramData == nil {
		return
	}
	sec := paramData.GetArrivingSec()

	checkSec := timeUtil.CheckAeSecValid(int(sec))
	if !checkSec {
		return errors.New("invalid sec")
	}
	deviceInfo, err := service.Device().GetByDeviceNo(ctx, deviceNo)
	if err != nil {
		return err
	}
	if deviceInfo.OpenStatus != consts.OpenStatusActive {
		return errors.New("device is not open")
	}
	productInfo, err := service.Product().GetByProductId(ctx, deviceInfo.ProductId)
	if err != nil || productInfo == nil || productInfo.Id == 0 {
		return errors.New("invalid product")
	}
	switch productInfo.ProductKey {
	case consts.ProductKeyM1:
		err = s.implementReceiveParamDataAE(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyM2:
		err = s.implementReceiveParamDataAE(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyVI1:
		err = s.implementReceiveParamDataVI(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyVI2:
		err = s.implementReceiveParamDataVI(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyM1V1:
		err = s.implementReceiveParamDataAEVI(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyM1V2:
		err = s.implementReceiveParamDataAEVI(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyM2V1:
		err = s.implementReceiveParamDataAEVI(ctx, message)
		if err != nil {
			return
		}
	case consts.ProductKeyM2V2:
		err = s.implementReceiveParamDataAEVI(ctx, message)
		if err != nil {
			return
		}
	}
	return nil
}

func (s *sAeemqx) handleAeIotDeviceOpResponse(ctx context.Context, message *pb.SensorMessage) (err error) {
	if message == nil {
		return
	}
	info := message.GetIotDeviceOpResponse()
	if info == nil {
		return
	}
	sn := message.GetNodeId()
	sns := message.GetNodeIds()
	tablesn := sn
	if sns != nil && len(sns) > 1 {
		tablesn = strings.Join(message.GetNodeIds(), ",")
	}
	deviceInfo, err := service.Device().GetByDeviceNo(ctx, sn)
	if err != nil || deviceInfo == nil || deviceInfo.Id == 0 {
		return errors.New("invalid device")
	}
	if len(tablesn) >= 1000 { //避免太多 这里只是通知 不用特别准确
		tablesn = tablesn[:999] //截取一部分通知就行
	}

	thisType := ""

	//实际更改配置
	switch info.Msg.(type) {
	case *pb.IotDeviceOpResponse_AeMeasureConfig:
		thisType = consts.DeviceConfTypeParamConfig
		thisConfig := info.GetAeMeasureConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleAeMeasureConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleAeMeasureConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
	case *pb.IotDeviceOpResponse_AeTimingConfig:
		thisType = consts.DeviceConfTypeTimingConfig
		thisConfig := info.GetAeTimingConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleAeTimingConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleAeTimingConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
		break
	case *pb.IotDeviceOpResponse_AeFFTConfig:
		thisType = consts.DeviceConfTypeAeFftConfig
		thisConfig := info.GetAeFFTConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleAeFFTConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleAeFFTConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
		break
	case *pb.IotDeviceOpResponse_FirConfig:
		thisType = consts.DeviceConfTypeFirConfig
		thisConfig := info.GetFirConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleAeFirConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleAeFirConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
		break
	case *pb.IotDeviceOpResponse_LevelConfig:
		thisType = consts.DeviceConfTypeLevelConfig2
		thisConfig := info.GetLevelConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				//v2版本评级
				err = s.implementHandleLevelConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			//v2版本评级
			err = s.implementHandleLevelConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
		break
	case *pb.IotDeviceOpResponse_ViMeasureConfig:
		thisType = consts.DeviceConfTypeViMeasureConfig
		thisConfig := info.GetViMeasureConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleViMeasureConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleViMeasureConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
		break
	case *pb.IotDeviceOpResponse_FrpConfig:
		thisType = consts.DeviceConfTypeFrpConfig
		thisConfig := info.GetFrpConfig()
		if sns != nil && len(sns) > 0 {
			for _, item := range sns {
				err = s.implementHandleFrpConfig(ctx, item, thisConfig)
				if err != nil {
					return err
				}
			}
		} else {
			err = s.implementHandleFrpConfig(ctx, sn, thisConfig)
			if err != nil {
				return err
			}
		}
	default:
		break
	}
	if thisType != "" {
		_, err = dao.IotDeviceStateLog.Ctx(ctx).Insert(do.IotDeviceStateLog{
			DeviceNos: tablesn,
			DeptId:    deviceInfo.DeptId,
			CreatedAt: gtime.Now(),
			Type:      thisType,
			BigType:   consts.AeDeviceStateLogBigTypeOperate,
			Status:    info.Status,
			Value:     nil,
		})
		if err != nil {
			return err
		}
	}
	// 清理日志，如果上一次清理的时间距离现在超过1天，就清理IotDeviceStateLog一次，清理CreatedAt小于1天的日志
	if lastCleanDeviceStateLogTime.IsZero() || time.Now().Sub(lastCleanDeviceStateLogTime.Time) > 24*time.Hour {
		_, err = dao.IotDeviceStateLog.Ctx(ctx).Where("CreatedAt < ?", time.Now().Add(-24*time.Hour)).Delete()
		if err != nil {
			glog.Error(ctx, "清理IotDeviceStateLog失败:", err)
		} else {
			lastCleanDeviceStateLogTime = gtime.Now()
		}
	}

	//web消息推送
	msg := mymodel.WebsiteMessage{
		DeviceNos: tablesn,
		DeptId:    int64(deviceInfo.DeptId),
		CreatedAt: gtime.Now(),
		BigType:   consts.AeDeviceStateLogBigTypeOperate,
		Type:      thisType,
		Value:     "",
		Status:    int(info.Status),
	}
	jsonBytes, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	topic := consts.EMQX_TOPIC_WEBSUB + gconv.String(deviceInfo.DeptId)
	mqttconf, err := s.GetMqttConfByServerKey(ctx, consts.EnvConfig_Mqtt_Default)
	if err != nil {
		return err
	}
	if mqttconf == nil {
		return errors.New("mqtconf is nil")
	}
	_ = s.WebsiteMqttPublish(ctx, mqttconf, topic, jsonBytes)
	return
}
